/*
	types.h

	defines commonly used data types and functions for 64 bit

	Author: Aidan Goddard 23/4/13
*/

#ifndef TYPES_H_INCLUDED
#define TYPES_H_INCLUDED

#include<stdint.h>
#include<stddef.h>

// useful for CPP interop stuff
#ifdef __cplusplus
#define _Static_assert static_assert
#endif

// check size of size_t
#ifdef __GCC_CROSS__
_Static_assert ((sizeof(size_t) == 8), "size_t is not 8 bytes");
#endif

// define the kernel offset & kernel MMIO offset
#define KOFFSET 0xffffff8000000000ULL
#define KMMIO	0xffffff0000000000ULL

// functions to read and write to ports
static inline void outb(uint16_t port, uint8_t val)
{
	#ifdef __GCC_CROSS__
	__asm__ __volatile__("outb %0, %1" : : "a"(val), "Nd"(port));
	#endif
	return;
}

static inline uint8_t inb(uint16_t port)
{
	unsigned char ret = 0;
	#ifdef __GCC_CROSS__
	__asm__ __volatile__("inb %1, %0" : "=a"(ret) : "Nd"(port));
	#endif
	return ret;
}

static inline void io_wait()
{
	// port 0x80 is used for 'checkpoints' during POST.
	// The Linux kernel seems to think it is free for use :/
	#ifdef __GCC_CROSS__
	__asm__ __volatile__("outb %%al, $0x80"::"a"(0));
	#endif
	return;
}

// functions to read and write to and from MSRs
static inline void rdmsr(uint32_t msr, uint32_t *lo, uint32_t *hi)
{
	#ifdef __GCC_CROSS__
	__asm__ __volatile__("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
	#endif
	return;
}

static inline void wrmsr(uint32_t msr, uint32_t lo, uint32_t hi)
{
	#ifdef __GCC_CROSS__
	__asm__ __volatile__("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
	#endif
	return;
}

// function to invalidate a virtual memory page
static inline void invlpg(uint64_t addr)
{
	#ifdef __GCC_CROSS__
   __asm__ __volatile__("invlpg (%0)" ::"r" (addr) : "memory");
	#endif
   return;
}

#endif






